import math
from typing import Tuple, Dict, Any

import networkx as nx
import numpy as np
from matplotlib import pyplot as plt
from python.lib import json

from DHTOA1 import load_traffic_data, process_traffic_scenario, calculate_total_delay, semi_calculate_static_latency
from allocate_switches_with_es_optimized import allocate_switches_with_es_optimized, allocate_electric_with_es_optimized
from calculate_optical_delay import calculate_communication_delay
from electric_path_algo import allocate_paths, widest_path
from find_min_max_delay_path import optimize_reconfiguration, find_min_max_delay_path
from find_min_max_delay_path_optimize import classify_traffic_paths, compute_max_delay, dynamic_traffic_reconfiguration, \
    update_link_capacities
from find_min_max_delay_path_test import matrix_to_communication_pairs
from optimize import find_optimal_electric_paths, calculate_no_recon_utilization, find_recon_electric_optical_paths, \
    initialize_utilization, calculate_communication_metrics, calculate_network_metrics, calculate_communication_times
# from optimize import find_electric_path_pairs
from topo1 import build_hybrid_topology_shared_tor,visualize_topology
from switchesalgo import allocate_switches_with_es

print("--------------------4节点-----------------------------")
topo1=build_hybrid_topology_shared_tor(num_tor=4)
topo2=build_hybrid_topology_shared_tor(num_tor=8)
topo3=build_hybrid_topology_shared_tor(num_tor=16)

# 加载流量数据
with open("traffic_matrices.json",'r') as f:
    traffic_matrices = json.load(f)
 # 提取不同节点数量下的 all_to_all 流量矩阵
all_to_all_4 = traffic_matrices['4_nodes']['all_to_all']
# 计算流量矩阵中所有元素的和
all_to_all_4_sum = sum(sum(row) for row in all_to_all_4)
print("all_to_all_4_sum:", all_to_all_4_sum)
all_to_all_4_matrix = np.array(all_to_all_4)
all_to_all_4_dict = matrix_to_communication_pairs(all_to_all_4_matrix, node_prefix="ToR")
T0_pair=matrix_to_communication_pairs(all_to_all_4_matrix, node_prefix="ToR")
T0=[]
for pair in T0_pair:
    T0.append(pair)

burst_traffic_4= traffic_matrices['4_nodes']['burst_traffic']

all_to_all_burst_4= traffic_matrices['4_nodes']['all_to_all_burst']
all_to_all_burst_4_sum = sum(sum(row) for row in all_to_all_burst_4)
print("all_to_all_burst_4_sum:", all_to_all_burst_4_sum)
all_to_all_burst_4_matrix = np.array(all_to_all_burst_4)
all_to_all_burst_4_dict = matrix_to_communication_pairs(all_to_all_burst_4_matrix, node_prefix="ToR")
T_pair=matrix_to_communication_pairs(all_to_all_burst_4_matrix, node_prefix="ToR")
T=[]
for pair in T_pair:
    T.append(pair)
# tor_switches = {'ToR1', 'ToR2', 'ToR3', 'ToR4','ToR5', 'ToR6', 'ToR7', 'ToR8','ToR9', 'ToR10', 'ToR11', 'ToR12','ToR13', 'ToR14', 'ToR15', 'ToR4'}
# optical_switches = {'os1', 'os2','os3', 'os4'}
# tor_switches = {'ToR1', 'ToR2', 'ToR3', 'ToR4','ToR5', 'ToR6', 'ToR7', 'ToR8'}
# optical_switches = {'os1', 'os2','os3', 'os4','os5', 'os6','os7', 'os8'}
tor_switches = {'ToR1', 'ToR2', 'ToR3', 'ToR4'}
optical_switches = {'os1', 'os2','os3', 'os4'}


# 没有突发流量前的通信对的最优路径
paths0, util0, delays0 = allocate_switches_with_es_optimized(topo1, T, all_to_all_4_dict, tor_switches, optical_switches,
                                                k_paths=500)
# 有突发流量前的通信对的最优路径
paths, util, delays = allocate_switches_with_es_optimized(topo1, T, all_to_all_burst_4_dict, tor_switches, optical_switches,
                                                k_paths=500)
print("============测试===================")
print(paths)
print(type(paths))
print(util)
print(delays)
print("============测试===================")
print("\n=== 基础流量矩阵的最优路径和流量分配 ===")
for pair, path in paths0.items():
    print(f"通信对 {pair}: 路径 {'→'.join(path)}")

for pair, rate in util0.items():
    print(f"链路 {pair}: 当前利用率={rate:.2f} Gbps")

for pair, delay in delays0.items():
    status = f"{delay:.2f}s" if delay not in [None, float('inf')] else "超时/未分配"
    print(f"通信对 {pair}: {status}")

print("\n=== 基础流量矩阵+突发流量矩阵的最优路径和流量分配 ===")
for pair, path in paths.items():
    print(f"通信对 {pair}: 路径 {'→'.join(path)}")

for pair, rate in util.items():
    print(f"链路 {pair}: 当前利用率={rate:.2f} Gbps")

for pair, delay in delays.items():
    status = f"{delay:.2f}s" if delay not in [None, float('inf')] else "超时/未分配"
    print(f"通信对 {pair}: {status}")

print("****************************全更新算法**************************")
def full_update_algorithm(topo1: nx.Graph,all_to_all_burst_4_dict : dict) -> tuple[dict[Any, float | Any], float]:
    # topo=topo1
    # traffic_demand=all_to_all_burst_4_dict
    # 获取需要重构和不需要重构的通信对
    recon_pairs, no_recon_pairs = classify_traffic_paths(all_to_all_burst_4_dict, paths0, paths)
    for recon_pair in recon_pairs:
        print(f"需要重构的通信对: {recon_pair}")

    for no_recon_pair in no_recon_pairs:
        print(f"不需要重构的通信对: {no_recon_pair}")
    # 计算不需要重构通信对的时间延迟
    for pair in no_recon_pairs:
        if pair in delays:
            print(f"不需要重构的通信对 {pair} 的延迟为 {delays[pair]}")


    # 计算不需要重构通信对链路利用率
    existing_utilization = calculate_no_recon_utilization(G=topo1, no_recon_pairs=no_recon_pairs,current_paths=paths,
                                                 traffic_demand=all_to_all_burst_4_dict, tor_switches=tor_switches,
                                                 k_paths=500)
    print("\n=== 不需要重构的链路利用率 ===")
    for pair, rate in existing_utilization.items():
        print(f"链路 {pair}: 当前已分配的流量为={rate:.2f} Gbps")

    # 为需要重构的通信对寻找最优的电链路
    # 获取不需要重构的通信对的流量需求
    electric_path_allocations, link_utilization, recon_electric_delay_info = allocate_electric_with_es_optimized(G=topo1, T=recon_pairs, D=all_to_all_burst_4_dict,
                                                    init_util=existing_utilization,tor_switches=tor_switches,optical_switches=optical_switches, k_paths=500)
    print("\n=== 为需要重构的通信对寻找最优的电链路 ===")
    for pair, path in electric_path_allocations.items():
        print(f"通信对 {pair}: 路径 {'→'.join(path)}")
    for pair, rate in link_utilization.items():
        print(f"链路 {pair}: 当前已分配的流量={rate:.2f} Gbps")
    for pair, delay in recon_electric_delay_info.items():
        status = f"{delay:.2f}s" if delay not in [None, float('inf')] else "超时/未分配"
        print(f"通信对 {pair}: {status}")

    recon_optical_delays=find_recon_electric_optical_paths(G=topo1, traffic_demand=all_to_all_burst_4_dict,current_paths=paths,recon_electric_delay_info=recon_electric_delay_info,recon_delay=10)
    # 合并不需要重构和需要重构的通信对延迟
    delays_1={}
    for pair in delays:
        if delays[pair] is None:
            continue
        else:
            delays_1[pair]=delays[pair]
    for pair in recon_optical_delays:
        if pair in delays:
            # delays_1[pair]=0.0
            delays_1[pair] = recon_optical_delays[pair] + 10.0
            print(f"通信对{pair}进行了重构")
            print(f"需要重构的通信对 {pair}延迟: {delays_1[pair]}")
        else:
            print(f"通信对{pair}不需要重构,通信时间为原来的")
    total_delays_1=0.0
    max_delays_1=0.0
    for pair in delays_1:
        if delays_1[pair] > max_delays_1:
            max_delays_1 = delays_1[pair]
        total_delays_1 += delays_1[pair]
    print("***********输出全更新算法的每个通信对的延迟以及所有通信对的延迟和=======================")
    for pair in delays_1:
        print(f"通信对 {pair}: {delays_1[pair]}")
    print(f"全更新路由算法的最大延迟为：{max_delays_1}")
    print(f"全更新路由算法所有通信对的延迟和为 {total_delays_1:.2f}s")
    return max_delays_1, total_delays_1
# print("===================测试====================")


print("==========================半更新路由算法（只更新电链路，不更新光链路）===========================")
def semi_update_algorithm(topo1: nx.Graph,all_to_all_burst_4_dict : dict) -> tuple[dict[Any, float | Any], float]:
    """半更新算法：仅更新电链路路径"""
    # 获取通信对中最优路径为电链路的通信对及路径
    need_recon_electric_pairs ={}
    no_need_recon_pairs0 ={}
    for pair in paths0:
        print(f"通信对 {pair}: 路径 {paths0[pair]}")
        # 遍历路径中的每一条链路
        for u, v in zip(paths0[pair], paths0[pair][1:]):
            # 如果链路类型为电链路，则更新路径
            if topo1[u][v].get('type', 'electrical') == 'electrical':
                need_recon_electric_pairs[pair] = paths0[pair]
                break
            no_need_recon_pairs0[pair]=paths0[pair]

    # print("================测试================")
    # for pair in no_need_recon_pairs0:
    #     print(f"通信对 {pair}: 路径 {no_need_recon_pairs0[pair]}")
    T_no_need_recon_pairs0=[]
    for pair in no_need_recon_pairs0:
        T_no_need_recon_pairs0.append(pair)
    print("不需要重构的通信对：")
    existing_utilization0 = calculate_no_recon_utilization(G=topo1, no_recon_pairs=T_no_need_recon_pairs0,current_paths=paths0,
                                                 traffic_demand=all_to_all_burst_4_dict, tor_switches=tor_switches,
                                                 k_paths=500)
    print("================测试================")

    for pair, rate in existing_utilization0.items():
        print(f"链路 {pair}: 当前已分配的流量为={rate:.2f} Gbps")
    print("================测试================")
    # 遍历需要重构的通信对，将他们的电链路初始化已分配的流量为0.0
    T=[]
    for pair, path in need_recon_electric_pairs.items():
    # for pair, path in paths0.items():
        print(f"通信对 {pair}: 路径 {'→'.join(path)}")
        T.append(pair)
        # 遍历路径中的每一条链路
        for u, v in zip(path, path[1:]):
            # 如果链路类型为电链路，则更新路径上已分配的流量为0.0
            if topo1[u][v].get('type') == 'electrical':
                print(f"链路 {(u, v)} 的已分配流量已重置为0.0")
                existing_utilization0[(u, v)]=0.0
                existing_utilization0[(v, u)]=0.0
            else:
                print(f"链路 {(u, v)} 的已分配流量未改变")


    # T=[]
    # for pair in  no_recon_pairs:
    #     T.append(pair)
    # # 基于不需要重构的通信对初始化每条链路上已经分配的流量
    # communication_times0, link_allocations0=calculate_communication_metrics(topo1, all_to_all_burst_4_dict, T, paths0)
    # # 如果链路在不在link_allocations0中，则初始化该链路的已分配流量为0.0,如果在则初始化为link_allocations0中对应的值
    # for edge in topo1.edges():
    #     if edge not in link_allocations0:
    #         existing_utilization[edge]=0.0
    #         existing_utilization[(edge[1],edge[0])]=0.0
    #     else:
    #         existing_utilization[edge]=link_allocations0[edge]
    #         existing_utilization[(edge[1],edge[0])]=link_allocations0[edge]
    # 为需要重构的通信对寻找最优的电链路
    electric_path_allocations, link_utilization, recon_electric_delay_info = allocate_electric_with_es_optimized(G=topo1, T=T, D=all_to_all_burst_4_dict,
                                                    init_util=existing_utilization0,tor_switches=tor_switches,optical_switches=optical_switches, k_paths=500)
    for pair, path in electric_path_allocations.items():
        print(f"通信对 {pair}: 路径 {'→'.join(path)}")
    for pair, rate in link_utilization.items():
        print(f"链路 {pair}: 当前已分配的流量={rate:.2f} Gbps")
    for pair, delay in recon_electric_delay_info.items():
        status = f"{delay:.2f}s" if delay not in [None, float('inf')] else "超时/未分配"
        print(f"通信对 {pair}: {status}")

    print("输出不需要重构的通信对的通信时间：")
    T_2=[]
    for pair in no_need_recon_pairs0:
        T_2.append(pair)
    comm_time = calculate_communication_times(topo1, all_to_all_burst_4_dict, T_2, paths0)
    for pair, time in comm_time.items():
        print(f"不需要重构的通信对 {pair}: 通信时间={time:.2f} s")

    print("***********输出半更新算法的每个通信对的延迟以及所有通信对的延迟和=======================")
    delays_2={}
    for pair in comm_time:
        if comm_time[pair] is None:
            continue
        else:
            delays_2[pair]=comm_time[pair]
    for pair in recon_electric_delay_info:
        # if pair in delays_2:
        delays_2[pair] = recon_electric_delay_info[pair]
        print(f"通信对{pair}进行了重构")
        print(f"需要重构的通信对 {pair}延迟: {delays_2[pair]}")
        # else:
        #     print(f"通信对{pair}不需要重构,通信时间为原来的")
    total_delays_2=0.0
    max_delays_2=0.0
    for pair in delays_2:
        if delays_2[pair] > max_delays_2:
            max_delays_2 = delays_2[pair]
        print(f"通信对延迟为 {pair}: {delays_2[pair]}")
        total_delays_2 += delays_2[pair]
    print(f"半更新路由算法的最大通信对延迟为 {max_delays_2:.2f}s")
    print(f"半更新路由算法的所有通信对的延迟和为 {total_delays_2:.2f}s")
    return delays_2, total_delays_2


print("==================固定路由算法（纯走电链路）==================")
def electric_only_algorithm(topo1: nx.Graph, all_to_all_burst_4_dict: dict) -> tuple[dict[Any, Any], float]:
    """纯电算法：仅使用电链路传输"""
    # 没有突发流量前的通信对的最优路径
    # 有突发流量前的通信对的最优路径
    paths, util, delays = allocate_switches_with_es_optimized(topo1, T, all_to_all_burst_4_dict, tor_switches,
                                                              optical_switches,
                                                              k_paths=500)
    T_1=[]
    for pair in paths:
        T_1.append(pair)
    # 创建新的初始化字典，完全基于当前拓扑
    util = initialize_utilization(topo1)
    electric_path_allocations, link_utilization, recon_electric_delay_info = allocate_electric_with_es_optimized(G=topo1, T=T_1, D=all_to_all_burst_4_dict,
                                                    init_util=util,tor_switches=tor_switches,optical_switches=optical_switches, k_paths=500)

    for pair, path in electric_path_allocations.items():
        print(f"通信对 {pair}: 路径 {'→'.join(path)}")
    for pair, rate in link_utilization.items():
        print(f"链路 {pair}: 当前已分配的流量={rate:.2f} Gbps")
    for pair, delay in recon_electric_delay_info.items():
        status = f"{delay:.2f}s" if delay not in [None, float('inf')] else "超时/未分配"
        print(f"通信对 {pair}: {status}")

    print("***********输出固定（只走电链路）算法的每个通信对的延迟以及所有通信对的延迟和=======================")
    delays_3={}
    total_delays_3=0.0
    max_delays_3=0.0
    for pair in recon_electric_delay_info:
        if recon_electric_delay_info[pair] is None:
            continue
        else:
            delays_3[pair]=recon_electric_delay_info[pair]
            print(f"通信对 {pair}延迟: {delays_3[pair]}")
    for pair in delays_3:
        if delays_3[pair]>max_delays_3:
            max_delays_3=delays_3[pair]
        # print(f"通信对延迟为 {pair}: {delays_3[pair]}")
        total_delays_3 += delays_3[pair]
    print(f"固定路由算法（纯电链路）的最大通信对延迟为 {max_delays_3:.2f}s")
    print(f"固定路由算法（纯点链路）的所有通信对的延迟和为 {total_delays_3:.2f}s")
    return delays_3, total_delays_3

print("==================固定路由算法（光电混合链路）==================")
def hybrid_static_algorithm(topo1: nx.Graph, traffic_demand: dict) -> tuple[dict[Any, Any], float]:
    """静态混合算法：固定光电路径分配"""
    T_3=[]
    for pair in paths0:
        print(f"通信对 {pair}: 路径 {'→'.join(paths0[pair])}")
        T_3.append(pair)

    communication_times, link_allocations=calculate_communication_metrics(topo1, all_to_all_burst_4_dict, T_3, paths0)
    for pair, time in communication_times.items():
        print(f"通信对 {pair}: 预估延迟={time:.2f}s")

    print(type(link_allocations))
    for pair, path in link_allocations.items():
        print(f"链路 {pair}已经分配的流量为:{link_allocations[pair]} ")

    print("***********输出固定（光电混合链路）算法的每个通信对的延迟以及所有通信对的延迟和=======================")
    delays_4={}
    total_delays_4=0.0
    max_delays_4=0.0
    for pair in communication_times:
        if communication_times[pair] is None:
            continue
        else:
            delays_4[pair]=communication_times[pair]
            print(f"通信对 {pair}延迟: {delays_4[pair]}")
    for pair in delays_4:
        if delays_4[pair] > max_delays_4:
            max_delays_4=delays_4[pair]
        # print(f"通信对延迟为 {pair}: {delays_4[pair]}")
        total_delays_4 += delays_4[pair]
    print(f"固定路由算法（光电混合链路）的最大通信对延迟为 {max_delays_4:.2f}s")
    print(f"固定路由算法（光电混合链路）的所有通信对的延迟和为 {total_delays_4:.2f}s")
    return delays_4, total_delays_4

if __name__ == "__main__":
    tor_switches = {'ToR1', 'ToR2', 'ToR3', 'ToR4'}
    optical_switches = {'os1', 'os2', 'os3', 'os4'}
    # 生成流量需求矩阵

    # 调用四个算法
    delays_1, total_delays_1 = full_update_algorithm(topo1, all_to_all_burst_4_dict)
    delays_2, total_delays_2 = semi_update_algorithm(topo1, all_to_all_burst_4_dict)
    delays_3, total_delays_3 = electric_only_algorithm(topo1, all_to_all_burst_4_dict)
    delays_4, total_delays_4 = hybrid_static_algorithm(topo1, all_to_all_burst_4_dict)






